define(["lib/jQueryBundle!touchpunch", "utils", "images"], function($, utils, images) {
    var create = function(pluginHost) {

        //plugin parameters
        var bitmapScale = 1;
        var imageUrl = images.getImage(pluginHost.questionDefinition).src;
        var imageWidth = getImageWidth(imageUrl);
        var imageHeight = getImageWidth(imageUrl);
        var settings = {defaultColor: "#ff0", defaultOpacity: 0.5, defaultSize:25};
        var noBitsPerInteger = 64;

        var isComplete = function() {
            return true;
        };

        var createView = function() {
            var $canvas = $("<canvas></canvas>");
            $canvas.attr("id", "highlighter");

            $canvas.css("background-image", utils.formatString("url('{0}')", [imageUrl]));
            //Hardcoded mouse cursor. Supposed to be in a CSS file but not sure how to import css plus the image as external resources
            $canvas.hover(function() {
                $(this).css("cursor", utils.formatString("url('{0}') 10 15", ["https://dl.dropboxusercontent.com/1/view/gdrwin5oh1w8qus/Public/highlighter-stamp-image.png"]));
            });
            $canvas.attr("width", imageWidth);
            $canvas.attr("height", imageHeight);

            var highLighter = new Sketch($canvas[0], settings);
            $canvas.data('sketch', highLighter);

            return result = $("<div id='highlighterMain'></div>")
                .append(getListOfButtons(highLighter))
                .append($canvas);
        };

        //TODO To be REFACTORED TO images library
        function getImageWidth(imageUrl){
            return imageUrl.match(/&w=(\d+)*/)[1];
        }

        //TODO To be REFACTORED TO images library
        function getImageHeight(imageUrl){
            return imageUrl.match(/&h=(\d+)*/)[1];
        }

        function getListOfButtons(highlighter) {
            //TODO Could be using handle bar template
            var $controlPanel = $("<div id='HighlighterButtons'></div>");

            var $clearAllButton = $("<span style='border:1px black solid; margin:2px;'><a>Clear All</a></span>").on('click', function(e) {
                highlighter.clearCanvas()
            });
            var $paintButton = $("<span style='border:1px black solid; margin:2px;'><a>Paint Mode</a></span>").on('click', function(e) {
                highlighter.tool = 'marker';
            });
            var $eraseButton = $("<span style='border:1px black solid; margin:2px;'><a>Erase Mode</a></span>").on('click', function(e) {
                highlighter.tool = 'eraser';
            });
            var $undoButton = $("<span style='border:1px black solid; margin:2px;'><a>Undo</a></span>").on('click', function(e) {
                highlighter.undo();
            });
            var $redoButton = $("<span style='border:1px black solid; margin:2px;'><a>Redo</a></span>").on('click', function(e) {
                highlighter.redo();
            });
            var $bitmapButton = $("<span style='border:1px black solid; margin:2px;'><a>Bitmap Export</a></span>").on('click', function(e) {
                highlighter.exportBits(false);
            });
            var $optimizedBitmapButton = $("<span style='border:1px black solid; margin:2px;'><a>Bitwise ("+noBitsPerInteger+") Export</a></span>").on('click', function(e) {
                highlighter.exportBits(true);
            });
            var $downloadButton = $("<span style='border:1px black solid; margin:2px;'><a>Image Export</a></span>").on('click', function(e) {
                highlighter.download();
            });
			var $saveButton = $("<span style='border:1px black solid; margin:2px;'><a>Save</a></span>").on('click', function(e) {
                highlighter.save();
            });

            $controlPanel.append($clearAllButton).append($paintButton).append($eraseButton)
                .append($undoButton).append($redoButton).append($bitmapButton).append($optimizedBitmapButton)
                .append($downloadButton).append($saveButton);

            return $controlPanel;
        };

        var Sketch;

        Sketch = (function () {
            function Sketch(el, opts) {
                this.el = el;
                this.canvas = $(el);
                this.context = el.getContext('2d');
                this.options = $.extend({
                    toolLinks: true,
                    defaultTool: 'marker',
                    defaultColor: '#000000',
                    defaultOpacity: 1,
                    defaultSize: 5
                }, opts);
                this.painting = false;
                this.color = this.options.defaultColor;
                this.opacity = this.options.defaultOpacity;
                this.size = this.options.defaultSize;
                this.tool = this.options.defaultTool;
                this.actions = [];
                this.undidActions = [];
                this.action = [];
                this.canvas.bind('click mousedown mouseup mousemove mouseleave mouseout touchstart touchmove touchend touchcancel', this.onEvent);
            }
            Sketch.prototype.clearCanvas = function () {
                this.context.clearRect(0, 0, this.el.width, this.el.height);
                this.actions = [];
                this.undidActions = [];
            };

            Sketch.prototype.download = function (format) {
                var mime;
                format || (format = "png");
                if (format === "jpg") {
                    format = "jpeg";
                }
                mime = "image/" + format;
                return window.open(this.el.toDataURL(mime));
            };
            Sketch.prototype.set = function (key, value) {
                console.log("sketch.change");
                this[key] = value;
                return this.canvas.trigger("sketch.change" + key, value);
            };
            Sketch.prototype.startPainting = function () {
                console.log("startPainting");
                this.painting = true;
                return this.action = {
                    tool: this.tool,
                    color: this.color,
                    opacity: this.opacity,
                    size: parseFloat(this.size),
                    events: []
                };
            };
            Sketch.prototype.stopPainting = function () {
                if (this.action) {
                    this.actions.push(this.action);
                }
                this.painting = false;
                this.action = null;
                this.actionsFixup();
                return this.redraw();
            };
            Sketch.prototype.onEvent = function (e) {
                if (e.originalEvent && e.originalEvent.targetTouches) {
                    e.pageX = e.originalEvent.targetTouches[0].pageX;
                    e.pageY = e.originalEvent.targetTouches[0].pageY;
                }
                $.sketch.tools[$(this).data('sketch').tool].onEvent.call($(this).data('sketch'), e);
                e.preventDefault();
                return false;
            };
            Sketch.prototype.redraw = function () {
                var sketch;
                this.el.width = this.canvas.width();
                this.context = this.el.getContext('2d');
                sketch = this;
                $.each(this.actions, function () {
                    if (this.tool) {
                        return $.sketch.tools[this.tool].draw.call(sketch, this);
                    }
                });
                if (this.painting && this.action) {
                    return $.sketch.tools[this.action.tool].draw.call(sketch, this.action);
                }
            };
            Sketch.prototype.undo = function() {
                if (this.actions.length > 0) {
                    this.undidActions.push(this.actions.pop());
                    this.redraw();
                }
            };
            Sketch.prototype.redo = function() {
                if (this.undidActions.length > 0) {
                    this.actions.push(this.undidActions.pop());
                    this.redraw();
                }
            };
            Sketch.prototype.actionsFixup = function() {
                var toAddHalfPoint = false;
                var i = this.actions.length - 1;

                if (this.actions[i].events.length === 1){
                    toAddHalfPoint = true;

                }
                else if (this.actions[i].events.length > 1){
                    var lastX = this.actions[i].events[0].x;
                    var lastY = this.actions[i].events[0].y;
                    for(var j = 1; j < this.actions[i].events.length; j++) {
                        toAddHalfPoint = true;
                        if (lastX !== this.actions[i].events[j].x || lastY !== this.actions[i].events[j].y) {
                            toAddHalfPoint = false;
                            break;
                        }
                    }
                }
                if (toAddHalfPoint) {
                    var firstEvent = this.actions[i].events[0];
                    this.actions[i].events.push({event: "mousedown", x: firstEvent.x + 0.5, y: firstEvent.y + 0.5})
                }
            };
            Sketch.prototype.exportBits = function(optimized) {
                var result = "";

                var imageData = this.context.getImageData(0,0,imageWidth, imageHeight);
                var scaledHeight = bitmapScale * imageHeight;
                var scaledWidth = bitmapScale * imageWidth;
                var imageDataIndex = 0;

                if (!optimized)
                {
                    for(var y = 0; y < scaledHeight; y++) {
                        for (var x = 0; x < scaledWidth; x++) {
                            imageDataIndex = ((y/bitmapScale * imageWidth) + (x/bitmapScale)) * 4;
                            if (imageData.data[imageDataIndex] != 0 || imageData.data[imageDataIndex + 1] != 0 || imageData.data[imageDataIndex + 2] != 0) {
                                result += "1";
                            }
                            else {
                                result += "0";
                            }
                        }
                        result += "\n";
                    }
                }
                else {
                    var bitwiseResult = 0;
                    var currentBitPosition = 0;

                    for(var y = 0; y < scaledHeight; y++) {
                        for (var x = 0; x < scaledWidth; x++) {
                            imageDataIndex = ((y/bitmapScale * imageWidth) + (x/bitmapScale)) * 4;
                            if (imageData.data[imageDataIndex] != 0 || imageData.data[imageDataIndex + 1] != 0 || imageData.data[imageDataIndex + 2] != 0) {
                                bitwiseResult = bitwiseResult << 1;
                                bitwiseResult += 1;
                            }
                            else {
                                bitwiseResult = bitwiseResult << 1;
                                bitwiseResult += 0;
                            }
                            currentBitPosition++;
                            if (currentBitPosition === noBitsPerInteger || (x+1 > scaledWidth) ) {
                                result += bitwiseResult + "|";
                                bitwiseResult = 0;
                                currentBitPosition = 0;
                            }
                        }
                        result += "\n";
                    }

                }
                alert("Length:" + result.length + " SampleWidth:" + scaledWidth + " SampleHeight:" + scaledHeight + "\n" + result);
            };
			
			var convertoToWkt = function (point) {
				return point.x + " " + point.y;
			};
			
			var trimWkt = function (wktString) {
				return wktString.substring(0, wktString.length - 2);
			}
			
			var multiLineStringConstant = "MULTILINESTRING (";
			
			Sketch.prototype.save = function() {
				var lineStrings = "";
				var strokes = _.filter(this.actions, function (action) {
					return _.isObject(action);
				});
				_.each(strokes, function (stroke) {
					var line = "";
					_.each(stroke.events, function(event) {						
						var wktPoint = convertoToWkt(event);
						if (line.indexOf(wktPoint) < 0) {
							line = line + convertoToWkt(event) + ", ";
						}
					});
					if (line.length > 0) {
						line = "(" + trimWkt(line) + "), ";
					}
					lineStrings = lineStrings + line;
				});
				lineStrings = trimWkt(lineStrings);
				var multiLineString = multiLineStringConstant + lineStrings + ")";
				console.log(multiLineString);
				
				//test to see if valid wkt
				var wkt = new Wkt.Wkt();
				var components = wkt.read(multiLineString);
				
				//save to open end
				pluginHost.dataStore.setOpenEndText(multiLineString);
			}

            return Sketch;
        })();
        $.sketch = {
            tools: {}
        };
        $.sketch.tools.marker = {
            onEvent: function (e) {
                //    console.log("marker.onEvent");
                switch (e.type) {
                    case 'mousedown':
                    case 'touchstart':
                        this.startPainting();
                        break;
                    case 'mouseup':
                    case 'mouseout':
                    case 'mouseleave':
                    case 'touchend':
                    case 'touchcancel':
                        this.stopPainting();
                }
                if (this.painting) {
                    this.action.events.push({
                        x: e.pageX - this.canvas.offset().left,
                        y: e.pageY - this.canvas.offset().top,
                        event: e.type
                    });
                    return this.redraw();
                }
            },
            draw: function (action) {
                /// console.log("marker.draw");
                var event, previous, _i, _len, _ref;
                this.context.lineJoin = "round";
                this.context.lineCap = "round";
                this.context.beginPath();
                this.context.moveTo(action.events[0].x, action.events[0].y);
                _ref = action.events;
                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                    event = _ref[_i];
                    this.context.lineTo(event.x, event.y);
                    previous = event;
                }
                this.context.strokeStyle = action.color;
                this.context.globalAlpha = action.opacity;
                this.context.lineWidth = action.size;
                return this.context.stroke();
            }
        };

        $.sketch.tools.eraser = {
            onEvent: function (e) {
                return $.sketch.tools.marker.onEvent.call(this, e);
            },
            draw: function (action) {
                var oldcomposite;
                oldcomposite = this.context.globalCompositeOperation;
                this.context.globalCompositeOperation = "destination-out";
                action.opacity = 1;
                $.sketch.tools.marker.draw.call(this, action);
                return this.context.globalCompositeOperation = oldcomposite;
            }
        };

        return {
            isComplete: isComplete,
            createView: createView,
            shouldRenderQuestionHeader: false,
            getObjectId: function() {
                return pluginHost.QuestionDefinition.ObjectId;
            }
        };
    };

    return {
        create: create
    };
});